﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
using Microsoft.Office.Server.Search.Administration;

namespace CrossSiteCollectionSearchConfigurator
{
    public class SearchSettingsPropogatorEngine
    {
        /// <summary>
        /// Don't want this instantiated, just use the static RunEngine method.
        /// </summary>
        private SearchSettingsPropogatorEngine()
        { }

        public static void RunEngine(SPWebApplication webApp)
        {
            //find the master & the slaves
            List<SPSite> slaveSiteCollections = new List<SPSite>();
            SPSite masterSiteCollection = null;
            foreach (SPSite site in webApp.Sites)
            {
                SPWeb rootWeb = site.RootWeb;

                bool isMaster = Utilities.CheckIsMaster(rootWeb);
                bool isSlave = Utilities.CheckIsSlave(rootWeb);

                if (isMaster)
                {
                    masterSiteCollection = site;
                }
                if (isSlave)
                {
                    slaveSiteCollections.Add(site);
                }

                rootWeb.Dispose();
                //Only dispose the sites we're not using later.
                if (masterSiteCollection != site
                    && !slaveSiteCollections.Contains(site))
                {
                    site.Dispose();
                }
            }
            if (null == masterSiteCollection)
            {
                return;
            }
            //Get the keywords from the master.
            SearchContext siteSearchContext = SearchContext.GetContext(masterSiteCollection);
            Keywords keywords = new Keywords(siteSearchContext, new Uri(masterSiteCollection.Url));
            KeywordCollection masterKeywords = keywords.AllKeywords;
            

            foreach (SPSite slaveSite in slaveSiteCollections)
            {
                SearchContext slaveContext = SearchContext.GetContext(slaveSite);
                Keywords slaveKeywords = new Keywords(slaveContext, new Uri(slaveSite.Url));

                //clear the current set of keywords.
                List<Keyword> deleteKeyword = new List<Keyword>();
                KeywordsEnumerator slaveKeywordEmunerator = new KeywordsEnumerator(slaveKeywords.AllKeywords);
                while (slaveKeywordEmunerator.MoveNext())
                {
                    Keyword slaveKeyword = slaveKeywordEmunerator.Current;
                    deleteKeyword.Add(slaveKeyword);
                }
                for(int index = deleteKeyword.Count - 1; index >= 0; index--)
                {
                    deleteKeyword[index].Delete();
                }

                KeywordsEnumerator masterKeywordEmunerator = new KeywordsEnumerator(masterKeywords);
                while (masterKeywordEmunerator.MoveNext())
                {
                    Keyword current = masterKeywordEmunerator.Current;
                    Keyword currentSlave = slaveKeywords.AllKeywords.Create(current.Term, current.StartDate);
                    currentSlave.ReviewDate = current.ReviewDate;
                    currentSlave.EndDate = current.EndDate;
                    currentSlave.Contact = current.Contact;
                    currentSlave.Definition = current.Definition;
                    
                    //now add the best bets....
                    BestBetCollection currentBestBets = current.BestBets;
                    BestBetsEnumerator currentBestBetEnumerator = new BestBetsEnumerator(currentBestBets);
                    while (currentBestBetEnumerator.MoveNext())
                    {
                        BestBet currentBestBet = currentBestBetEnumerator.Current;
                        BestBet slaveBestBet = currentSlave.BestBets.Create(currentBestBet.Title, 
                                                                             currentBestBet.Description, 
                                                                             currentBestBet.Url);
                    }

                    //now ensure that the synonyms match
                    SynonymCollection currentSynonyms = current.Synonyms;
                    SynonymsEnumerator currentSynonymEnumerator = new SynonymsEnumerator(currentSynonyms);
                    while (currentSynonymEnumerator.MoveNext())
                    {
                        Synonym currentSynonym = currentSynonymEnumerator.Current;
                        currentSlave.Synonyms.Create(currentSynonym.Term);
                    }
                    currentSlave.Update();
                }
                
            }
            return;
        }
    }
}
